perm filename QPROC.SAI[1,JRA] blob
sn#159073 filedate 1975-05-12 generic text, type T, neo UTF8
COMMENT ⊗ VALID 00016 PAGES
RECORD PAGE DESCRIPTION
00001 00001
00003 00002 BEGIN "QPROC"
00005 00003 PROCEDURE DO_INPUT(REFERENCE STRING SOURCEFILES
00009 00004 SIMPLE PROCEDURE INPUTERR(REFERENCE STRING CARD, CARD_AS_READ
00011 00005 SIMPLE PROCEDURE DO_PARMS
00016 00006 SIMPLE PROCEDURE CHECKPARMS
00018 00007 SIMPLE PROCEDURE DO_SCORES(INTEGER NQ)
00025 00008 α More of DO_SCORES -- CARD has been completely scanned
00027 00009 α The main part of PROCEDURE DO_INPUT
00029 00010 α More of main part of DO_INPUT -- input file now ready to be read
00033 00011 PROCEDURE DO_OUTPUT(REFERENCE STRING RESULTFILE
00037 00012 SIMPLE PROCEDURE HEADING1(SAFE STRING ARRAY PARMS
00040 00013 α Main part of procedure DO_OUTPUT
00043 00014 α Print scores for instructors
00047 00015 α Print data for t.a.s
00051 00016 α The main part of the main program
00052 ENDMK
⊗;
BEGIN "QPROC"
DEFINE !N_Q=14, !NINS_Q=13, !NTA_Q=!N_Q-!NINS_Q,
!CS=1, !IN=2, !TA=3, !EN=4,
!MAXSCORE=11,
!NPARMS=4,
NO="NOT", STARTLOOP="WHILE TRUE DO ", α="COMMENT",
TIL="STEP 1 UNTIL",
PAST_BLANKS=1, UP_TO_COMMA=2, UP_TO_SEMICOLON=3, UP_TO_EQ=4,
UP_TO_BLANK=5, UP_TO_CRLF=6,
!SYSPRG="NULL",
CR='15, LF='12, CRLF="('15&'12)", FF='14, TAB='11;
INTEGER Q;
SAFE INTEGER ARRAY TOTALANS[1:!N_Q], α for finding overall mean;
TOTALSCORES[1:!N_Q];
SAFE REAL ARRAY OVMEANS[1:!N_Q];
PRELOAD_WITH [14] 11;
SAFE INTEGER ARRAY MAXSCORES[1:!N_Q];
STRING SOURCEFILES, α file names -- this for input;
RESULTFILE; α and this for output;
REQUIRE 4000 NEW_ITEMS;
STRING ITEM CS_NAME, INSTRUCTOR, TEACHASST, ENROLLMENT, NUMBER_RESPS;
ITEM ISCORES, TSCORES;
INTEGER ITEM NUMBER_OF_INS, NUMBER_OF_TAS;
LIST CLASSLIST;
LABEL LBL;
PROCEDURE DO_INPUT(REFERENCE STRING SOURCEFILES;
REFERENCE LIST CLASSLIST;
SAFE INTEGER ARRAY MAXSCORES, TOTALANS, TOTALSCORES);
BEGIN "DO_INPUT"
BOOLEAN FOLLOWSPARM, ERROR;
STRING CARD, CARD_AS_READ, α input images;
FILENAME;
INTEGER I,
CARDNDX, α index of current card image in file;
CARDTYPE, α i.e., score or parm;
NRESPS, α # responding in the class;
INCHAN, BRCHAR, EOF, α for i/o;
NQ, α # score sets on a card (to avoid typing if no t.a.);
NINS, NTAS;
SAFE STRING ITEMVAR ARRAY PARMS[1:!NPARMS]; α for picking off parms and
printing out error messages;
SAFE STRING ARRAY PARMVALUES[1:!NPARMS];
STRING ITEMVAR CLASS;
LIST ISCLIST, TSCLIST; α to contain array items;
SAFE INTEGER ARRAY ISCINIT[1:!NINS_Q,0:!MAXSCORE], α for scores;
TSCINIT[1:!NTA_Q,0:!MAXSCORE];
SIMPLE PROCEDURE INPUTERR(REFERENCE STRING CARD, CARD_AS_READ;
INTEGER CARDNDX;
STRING FILENAME, ERRMSG);
BEGIN "INPUTERR"
CLRBUF;
OUTSTR(CRLF & "*** FILE=" & FILENAME & " CARD=" & CVS(CARDNDX) & CRLF);
OUTSTR(CARD_AS_READ[1 TO LENGTH(CARD_AS_READ)-LENGTH(CARD)] & LF & CARD);
OUTSTR(CRLF & "*** " & ERRMSG);
OUTSTR(CRLF & "RETYPE ENTIRE CARD." & CRLF & "→");
LODED(CARD_AS_READ);
CARD_AS_READ ← CARD ← INCHWL;
END "INPUTERR";
SIMPLE INTEGER PROCEDURE CLASSIFY(STRING C);
α Returns 2 if character is alphabetic, 3 if numeric, and 0 if neither;
IF C≥"0" AND C≤"9" THEN RETURN(3)
ELSE IF C≥"A" AND C≤"Z" THEN RETURN(2)
ELSE RETURN(0);
SIMPLE PROCEDURE DO_PARMS;
α CARD contains parameters, which are scanned off and entered into
the associative store. An error found anywhere on the card causes
rejection of the entire card;
BEGIN "DO_PARMS"
SAFE BOOLEAN OWN ARRAY PARMSEEN[1:!NPARMS];
STRING PARMNAME, PARMFIELD, NAME;
STRING ITEMVAR INS, TA;
INTEGER PARMNUM, I;
INTEGER ARRAY ITEMVAR ISC, TSC;
FOR I←1 TIL !NPARMS DO PARMSEEN[I]←FALSE;
WHILE CARD DO
α Scan off parameter and do the appropriate thing;
BEGIN
PARMFIELD←SCAN(CARD, UP_TO_SEMICOLON, BRCHAR);
PARMNAME←SCAN(PARMFIELD, UP_TO_EQ, BRCHAR);
PARMNUM←0;
FOR I←1 TIL !NPARMS DO
IF PARMNAME=DATUM(PARMS[I]) THEN α note use of numeric compare;
BEGIN
PARMNUM←I;
PARMSEEN[I]←TRUE;
PARMVALUES[I]←PARMFIELD;
DONE;
END;
IF NO PARMNUM THEN
BEGIN
INPUTERR(CARD, CARD_AS_READ, CARDNDX,
FILENAME, "INVALID PARAMETER.");
α CARD and CARD_AS_READ now have new values;
α Undo all parms specified on old card;
FOR I←1 TIL !NPARMS DO
IF PARMSEEN[I] THEN
BEGIN
PARMSEEN[I]←FALSE;
PARMVALUES[I]←NULL;
END;
END;
α Left-justify CARD again;
SCAN(CARD, PAST_BLANKS, BRCHAR);
END;
IF NO PARMNUM THEN RETURN; α since last parm processed was bad,
was uncorrected, and therefore
invalidated the whole card;
α Otherwise add parms to the associative store;
FOR I←1 TIL !NPARMS DO IF PARMSEEN[I] THEN CASE I OF
BEGIN
[!CS] BEGIN
DATUM(CLASS)←PARMVALUES[!CS];
MAKE CS_NAME ⊗ CLASS ≡ NEW(PARMVALUES[!CS]);
END;
[!IN] BEGIN
PARMFIELD←PARMVALUES[!IN];
NINS←0;
SCAN(PARMFIELD, PAST_BLANKS, BRCHAR);
IF BRCHAR THEN WHILE PARMFIELD DO
α Pick instructor names out of list;
BEGIN
NAME←SCAN(PARMFIELD, UP_TO_COMMA, BRCHAR);
SCAN(PARMFIELD, PAST_BLANKS, BRCHAR);
INS←NEW(NAME);
MAKE INSTRUCTOR ⊗ CLASS ≡ INS;
ISC←NEW(ISCINIT); α array for scores for the instr;
MAKE ISCORES ⊗ INS ≡ ISC;
PUT ISC IN ISCLIST AFTER ∞;
NINS←NINS+1;
END;
MAKE NUMBER_OF_INS ⊗ CLASS ≡ NEW(NINS);
END;
[!TA] BEGIN
PARMFIELD←PARMVALUES[!TA];
NTAS←0;
SCAN(PARMFIELD, PAST_BLANKS, BRCHAR);
IF BRCHAR THEN WHILE PARMFIELD DO
α Pick t.a. names from list and enter them;
BEGIN
NAME←SCAN(PARMFIELD, UP_TO_COMMA, BRCHAR);
SCAN(PARMFIELD, PAST_BLANKS, BRCHAR);
TA←NEW(NAME);
MAKE TEACHASST ⊗ CLASS ≡ TA;
TSC←NEW(TSCINIT); α array for scores for the t.a.;
MAKE TSCORES ⊗ TA ≡ TSC;
PUT TSC IN TSCLIST AFTER ∞;
NTAS←NTAS+1;
END;
MAKE NUMBER_OF_TAS ⊗ CLASS ≡ NEW(NTAS);
END;
[!EN] MAKE ENROLLMENT ⊗ CLASS ≡ NEW(PARMVALUES[!EN])
END;
END "DO_PARMS";
SIMPLE PROCEDURE CHECKPARMS;
α Checks to see that all parms have been specified before score
processing begins;
BEGIN "CHECKPARMS"
BOOLEAN ALLPARMS;
STRING ITEMVAR P;
INTEGER I;
ALLPARMS←TRUE;
FOR I←1 TIL !NPARMS DO
ALLPARMS←ALLPARMS AND PARMVALUES[I];
α Should have specified a blank field for an empty parm;
IF NOT ALLPARMS THEN
BEGIN
STRING TEMP;
CLRBUF;
FOR I←1 TIL !NPARMS DO
BEGIN
OUTSTR(CRLF & DATUM(PARMS[I]) & "=");
IF PARMS[I] ⊗ CLASS ≡ ANY THEN
FOREACH P | PARMS[I] ⊗ CLASS ≡ P DO
OUTSTR("""" & DATUM(P) & """ ")
ELSE OUTSTR("*** MISSING ***");
END;
OUTSTR(CRLF & LF & "TYPE IN PARMS CARD WITH REMAINING PARMS."
& CRLF & "→");
TEMP←CARD_AS_READ;
CARD_AS_READ←CARD←INCHWL;
DO_PARMS;
CARD_AS_READ←CARD←TEMP;
END;
END "CHECKPARMS";
SIMPLE PROCEDURE DO_SCORES(INTEGER NQ);
α CARD contains exactly NQ sets of scores.
A set of scores is either a single score, or more than one score, each
separated by commas. Depending on the question being processed, there
must be exactly one score in a set corresponding to each instructor or
t.a. in the class. A single score is "distributed" over each instructor
or t.a. A set of scores must contain no blanks.
Possible errors: too many or not enough sets of scores,
too many or not enough scores in a set,
invalid score (too big or too little).
In case of error, the entire card is rejected.
At least one instructor per class is assumed.
After the scores are successfully read, they are entered into the
associative store;
BEGIN "DO_SCORES"
INTEGER Q, Q1, NSC, I, J;
SHORT INTEGER K; SHORT REAL SC;
INTEGER ARRAY ITEMVAR ISC, TSC;
STRING SCODE, SCOREFIELD;
SCODE←NULL;
Q←1; α question number being processed;
α Here is where it is assumed that there's ≥ one instructor;
WHILE CARD OR Q≤NQ DO
α Pick each score off card and put code for it into SCODE;
BEGIN "SCAN_CARD"
IF Q>NQ THEN
BEGIN
INPUTERR(CARD, CARD_AS_READ, CARDNDX, FILENAME,
"TOO MANY SETS OF SCORES.");
α CARD and CARD_AS_READ are now replaced;
SCODE←NULL; α Discard code accumulated so far;
Q←1; α Restart question scanning;
CONTINUE;
END
ELSE IF NO CARD THEN
BEGIN
INPUTERR(CARD, CARD_AS_READ, CARDNDX, FILENAME,
"NOT ENOUGH SETS OF SCORES.");
α CARD and CARD_AS_READ are now replaced;
SCODE←NULL; α Discard code accumulated so far;
Q←1; α Restart question scanning;
CONTINUE;
END
ELSE NSC ← IF Q≤!NINS_Q THEN NINS ELSE NTAS;
α That defined the number of scores to be expected;
SCOREFIELD←SCAN(CARD, UP_TO_BLANK, BRCHAR);
SC←REALSCAN(SCOREFIELD, BRCHAR);
α Two possibilities: in SCOREFIELD is either
a single number, which is the score for all instrs or t.a.s, or
a list of numbers separated by commas -- exactly one score for
each instr or t.a. (depending on the question);
IF NO BRCHAR THEN α just one score in SCOREFIELD;
IF (K←SC←2.0*SC)≥0 AND K≤MAXSCORES[Q] THEN
FOR I←1 TIL NSC DO SCODE←SCODE & K
ELSE α invalid score;
BEGIN
INPUTERR(CARD, CARD_AS_READ, CARDNDX,
FILENAME, "INVALID SCORE.");
α CARD and CARD_AS_READ are now replaced;
SCODE←NULL; α Discard code accumulated so far;
Q←0; α Restart question scanning;
END
ELSE α SCOREFIELD contains ≥1 score -- must have correct number;
FOR I←1 TIL NSC DO
BEGIN "SCAN_SET"
IF (K←SC←2.0*SC)≥0 AND K≤MAXSCORES[Q] THEN
SCODE←SCODE & K α Encode Ith score;
ELSE α invalid score;
BEGIN
INPUTERR(CARD←SCOREFIELD & CARD, CARD_AS_READ,
CARDNDX, FILENAME, "INVALID SCORE.");
α CARD and CARD_AS_READ are now replaced;
SCOREFIELD←SCODE←NULL; α Discard code accumulated so far;
Q←0; α Restart question scanning;
DONE;
END;
IF BRCHAR>0 α from the scan for the Ith score; THEN
IF I≠NSC THEN α get the I+1st score;
SC←REALSCAN(SCOREFIELD, BRCHAR)
ELSE α there was a break after getting the NSCth score;
BEGIN
INPUTERR(CARD, CARD_AS_READ, CARDNDX,
FILENAME, "TOO MANY SCORES IN SET.");
α CARD and CARD_AS_READ are now replaced;
SCODE←NULL; α Discard code accumulated so far;
Q←0; α Restart question scanning;
DONE;
END
ELSE α no more scores; IF I≠NSC THEN
BEGIN
α Not enough scores for all instrs or t.a.s;
INPUTERR(CARD, CARD_AS_READ, CARDNDX,
FILENAME, "NOT ENOUGH SCORES IN SET.");
α CARD and CARD_AS_READ get new values;
SCODE←NULL; α Code from old card now worthless;
Q←0; α Restart question scan;
DONE;
END
END "SCAN_SET";
SCAN(CARD, PAST_BLANKS, BRCHAR);
Q←Q+1;
END "SCAN_CARD";
α More of DO_SCORES -- CARD has been completely scanned;
IF NOT EQU(SCODE, NULL) THEN
BEGIN
NRESPS←NRESPS+1;
FOR Q←1 TIL !NINS_Q DO FOR I←1 TIL NINS DO
BEGIN
ISC←ISCLIST[I];
IF J←LOP(SCODE) THEN
α a response was to question q for instr i;
BEGIN
TOTALANS[Q]←TOTALANS[Q]+1;
TOTALSCORES[Q]←TOTALSCORES[Q]+J; α no need to add if 0;
END;
DATUM(ISC)[Q,J]←DATUM(ISC)[Q,J]+1; α Record score;
END;
FOR Q←1 TIL !NTA_Q DO FOR I←1 TIL NTAS DO
BEGIN
TSC←TSCLIST[I];
IF J←LOP(SCODE) THEN
α a response was to question q for t.a. i;
BEGIN
Q1←Q+!NINS_Q;
TOTALANS[Q1]←TOTALANS[Q1]+1;
TOTALSCORES[Q1]←TOTALSCORES[Q1]+J; α no need to add if 0;
END;
DATUM(TSC)[Q,J]←DATUM(TSC)[Q,J]+1; α Record score;
END;
END;
END "DO_SCORES";
α The main part of PROCEDURE DO_INPUT;
OPEN(INCHAN←GETCHAN, "DSK", 1, 2, 0, 150, BRCHAR, EOF);
SETBREAK(PAST_BLANKS, " ", NULL, "XNR");
SETBREAK(UP_TO_COMMA, ",", NULL, "INS");
SETBREAK(UP_TO_SEMICOLON, ";", NULL, "INS");
SETBREAK(UP_TO_EQ, "=", NULL, "INS");
SETBREAK(UP_TO_BLANK, " ", NULL, "INS");
SETBREAK(UP_TO_CRLF, LF, CR, "INS");
DATUM(CS_NAME)←"CS";
DATUM(INSTRUCTOR)←"IN";
DATUM(TEACHASST)←"TA";
DATUM(ENROLLMENT)←"EN";
PARMS[!CS]←CS_NAME;
PARMS[!IN]←INSTRUCTOR;
PARMS[!TA]←TEACHASST;
PARMS[!EN]←ENROLLMENT;
FOLLOWSPARM←TRUE;
CLASS←NEW(NULL);
α Now process input;
WHILE SOURCEFILES DO
BEGIN "DO_EACH_FILE"
FILENAME←SCAN(SOURCEFILES, UP_TO_COMMA, BRCHAR);
STARTLOOP α to look up the input file;
BEGIN
LOOKUP(INCHAN, FILENAME, ERROR);
IF NO ERROR THEN DONE;
OUTSTR(CRLF & "INVALID SOURCE INPUT FILE: ");
OUTSTR(FILENAME);
OUTSTR(CRLF & "RESPECIFY? ");
IF NO FILENAME←INCHWL THEN
IF NO FILENAME←SCAN(SOURCEFILES, UP_TO_COMMA, BRCHAR) THEN DONE;
END;
IF NO FILENAME THEN CONTINUE;
α More of main part of DO_INPUT -- input file now ready to be read;
CARD←INPUT(INCHAN, UP_TO_CRLF);
IF EQU(CARD[1 FOR 9],"COMMENT ⊗") THEN α flush directory page;
BEGIN
OUTSTR("Skipping directory page." & CRLF);
WHILE (CARD←INPUT(INCHAN, UP_TO_CRLF))≠FF DO;
CARD←CARD[2 TO ∞];
END;
CARD_AS_READ←CARD;
CARDNDX←1;
WHILE NOT EOF DO
BEGIN "DO_EACH_CARD" α process the CARDNDX'th card in the file;
IF INCHRS≠-1 THEN
OUTSTR(CRLF & "File = " & FILENAME & " Card = " & CVS(CARDNDX));
SCAN(CARD, PAST_BLANKS, BRCHAR);
CARDTYPE←CLASSIFY(BRCHAR);
CASE CARDTYPE OF
BEGIN
α error; BEGIN
INPUTERR(CARD, CARD_AS_READ, CARDNDX,
FILENAME, "UNRECOGNIZABLE CARD.");
α CARD and CARD_AS_READ are replaced by corrected versions;
IF CARD THEN CONTINUE; α skips past read;
END;
α comment; BEGIN α card is to be ignored; END;
α parm; BEGIN
IF NOT FOLLOWSPARM THEN
α End of a set of scores.
Finish off last class and start a new one;
BEGIN
MAKE NUMBER_RESPS ⊗ CLASS ≡ NEW(CVS(NRESPS));
PUT CLASS IN CLASSLIST AFTER ∞;
CLASS←NEW(NULL);
FOR I←1 TIL !NPARMS DO PARMVALUES[I]←NULL;
NINS←NTAS←0;
ISCLIST←TSCLIST←NIL;
END;
DO_PARMS;
FOLLOWSPARM←TRUE;
END;
α score; BEGIN
IF FOLLOWSPARM THEN
α All parms must have been specified for score processing
to start. CHECKPARMS checks that;
BEGIN
CHECKPARMS;
α Assuming here that there's at least one instr;
NQ←IF NTAS THEN !N_Q ELSE !NINS_Q;
NRESPS←0; α since starting a new file;
END;
DO_SCORES(NQ); α Argument is # of score sets on CARD;
FOLLOWSPARM←FALSE;
END;
END;
IF (CARD←INPUT(INCHAN, UP_TO_CRLF))=FF THEN CARD←CARD[2 TO ∞];
CARD_AS_READ←CARD;
CARDNDX←CARDNDX+1;
END "DO_EACH_CARD";
END "DO_EACH_FILE";
α Finish up last class;
MAKE NUMBER_RESPS ⊗ CLASS ≡ NEW(CVS(NRESPS));
PUT CLASS IN CLASSLIST AFTER ∞;
CLOSIN(INCHAN);
END "DO_INPUT";
PROCEDURE DO_OUTPUT(REFERENCE STRING RESULTFILE;
REFERENCE LIST CLASSLIST;
SAFE INTEGER ARRAY MAXSCORES;
SAFE REAL ARRAY OVMEANS);
BEGIN "DO_OUTPUT"
REQUIRE "⊂⊃⊂⊃" DELIMITERS;
α The following macro clears the current MRPP3 mode, enters center mode,
and sets the left and right margins for centering to L and R, resp.;
DEFINE TMPMARG(L,R)=⊂ OUT(OUTCHAN, "~←" & L & "~→l~←" & R & "~→r~c") ⊃;
PRELOAD_WITH
"General rating of the course as a whole." & CRLF,
"Give the instructor an overall rating." & CRLF,
"Instructor -- preparedness and organization of lectures" & CRLF,
"Instructor -- clarity of explanations" & CRLF,
"Instructor -- guidance of class discussion, question handling" & CRLF,
"Instructor -- willingness to help students" & CRLF,
"Instructor -- accessibility to students" & CRLF,
"Instructor -- encouragement of your interest in the subject" & CRLF,
"Rate the instructor's overall effort." & CRLF,
"Course content -- pace at which material was covered" & CRLF,
"Course content -- continuity" & CRLF,
"Course content -- clarity of course goals" & CRLF,
"Course content -- value of work expended" & CRLF;
SAFE OWN STRING ARRAY QUESTION[1:!N_Q];
PRELOAD_WITH [8] 1, 2, 3, 1, 1, 1;
SAFE OWN INTEGER ARRAY ANSTYPE[1:!N_Q];
PRELOAD_WITH
"excellent~.", "good~.", "satisfactory~.", "poor~.", "terrible~.",
"extraordinary~.", "a great deal~.", "a fair amount~.",
"very little~.", "almost zero~.",
"much too fast~.", "too fast~.", "about right~.", "too slow~.",
"much too slow~.";
SAFE OWN STRING ARRAY ANSWER[1:3, 1:!MAXSCORE % 2];
INTEGER OUTCHAN, M, R, Q, Q1, I, SUM, RESPS, ERROR, J, NINS, NTAS;
INTEGER ITEMVAR X;
SET PSET;
STRING ITEMVAR INS, TA, CLASS, U;
INTEGER ARRAY ITEMVAR ISC, TSC;
PRELOAD_WITH [!NINS_Q % 2] 0, 1, [!N_Q - 1 - !NINS_Q % 2] 0;
SAFE OWN BOOLEAN ARRAY SKIPAFTER[1:!N_Q]; α for inserting page breaks;
SAFE STRING ARRAY PARMS[1:!NPARMS+1]; α for parm vals and also # resps;
SIMPLE PROCEDURE HEADING1(SAFE STRING ARRAY PARMS;
INTEGER N;
STRING ITEMVAR P);
α A form-feed is output. A heading listing the parameters
of the given class follows. N is assumed to be the number of people
involved (either instructors or t.a.s) and if N is more than 1, a
subheading will be printed for person P;
BEGIN "HEADING1"
OUT(OUTCHAN, FF & "~F1~C"); α Select font;
OUT(OUTCHAN, PARMS[1]); α Class title;
OUT(OUTCHAN, CRLF & "~F2Instructor: "); α New font;
OUT(OUTCHAN, PARMS[2]); α Output list of instructors;
OUT(OUTCHAN, "~REnrolled: ");
OUT(OUTCHAN, PARMS[4]); α Output enrollment (right-justified);
OUT(OUTCHAN, CRLF & "Teaching asst: ");
OUT(OUTCHAN, PARMS[3]); α Output list of t.a.s;
OUT(OUTCHAN, "~RResponses: ");
OUT(OUTCHAN, PARMS[5]); α Output # responses (right-justified);
OUT(OUTCHAN, CRLF & LF & LF);
IF N>1 THEN α print subheading;
BEGIN
OUT(OUTCHAN, "Ratings for " & DATUM(P));
OUT(OUTCHAN, CRLF & LF);
END;
END "HEADING1";
SIMPLE PROCEDURE HEADING2(SAFE STRING ARRAY PARMS;
INTEGER N;
STRING ITEMVAR P);
α Class heading is printed;
BEGIN "HEADING2"
OUT(OUTCHAN, FF & "~F1~C"); α Select font;
OUT(OUTCHAN, PARMS[1]); α Class title;
OUT(OUTCHAN, CRLF & LF);
END "HEADING2";
SIMPLE PROCEDURE HEADING3(SAFE STRING ARRAY PARMS;
INTEGER N;
STRING ITEMVAR P;
BOOLEAN J);
α T.a. heading = class heading if at top of page (2 t.a.s per page).
If more than one t.a., subheading is printed;
BEGIN "HEADING3"
IF J THEN HEADING2(PARMS, N, P);
IF N>1 THEN α print subheading;
BEGIN
OUT(OUTCHAN, "~F2Ratings for " & DATUM(P));
OUT(OUTCHAN, CRLF & LF);
END;
END "HEADING3";
α Main part of procedure DO_OUTPUT;
OPEN(OUTCHAN←GETCHAN, "DSK", 1, 0, 2, 0, I, J);
STARTLOOP
BEGIN
ENTER(OUTCHAN, RESULTFILE, ERROR);
IF NO ERROR THEN DONE;
OUTSTR(CRLF & "INVALID RESULT FILE: ");
OUTSTR(RESULTFILE);
OUTSTR(CRLF & "RESPECIFY? ");
RESULTFILE←INCHWL;
END;
OUT(OUTCHAN, "~"); α Output leading escape character for MRPP3;
OUT(OUTCHAN, "~M1SET1" & !SYSPRG & ";~M2NGB25" & !SYSPRG
& ";~M3NGR25" & !SYSPRG & ";~M4NGR20" & !SYSPRG
& ";~." & CRLF); α Load fonts;
α Set tabs, each 1/15th farther across the page;
OUT(OUTCHAN, "~←R~-L~/=15;~→A~←L~→S~." & CRLF);
OUT(OUTCHAN, "~+A~→T~+A~→U~+A~→V~+A~→W~+A~→X~+A~→Y~+A~→Z~+A~→[~+A~→\~+A~→]" & CRLF);
OUT(OUTCHAN, "~+A~→↑~+A~→←~+A~→`~+A~→a~+A~→b~+A~→c~." & CRLF);
SETFORMAT(0,1); α print to one decimal place;
FOREACH CLASS | CLASS IN CLASSLIST DO
α Print class totals;
BEGIN "DO_EACH_CLASS"
α Fill up PARMS array;
FOR I←1 TIL !NPARMS DO PARMS[I]←NULL;
PARMS[1]←DATUM(CLASS); α Course name;
IF INCHRS≠-1 THEN OUTSTR(CRLF & "Class = " & PARMS[1]);
FOREACH U | ENROLLMENT ⊗ CLASS ≡ U DO PARMS[4]←DATUM(U); α Enrollment;
FOREACH U | NUMBER_RESPS ⊗ CLASS ≡ U DO PARMS[5]←DATUM(U); α # resps;
PSET←INSTRUCTOR ⊗ CLASS; α Form string of instructors' names;
U←LOP(PSET); α Always at least one instructor;
PARMS[2]←DATUM(U);
FOREACH U | U IN PSET DO PARMS[2]←PARMS[2] & ", " & DATUM(U);
IF (PSET←TEACHASST ⊗ CLASS)≠NIL THEN α form string of t.a.s' names;
BEGIN
U←LOP(PSET);
PARMS[3]←DATUM(U);
FOREACH U | U IN PSET DO PARMS[3]←PARMS[3] & ", " & DATUM(U);
END;
α Print scores for instructors;
FOREACH X | NUMBER_OF_INS ⊗ CLASS ≡ X DO NINS←DATUM(X);
FOREACH INS, ISC | INSTRUCTOR ⊗ CLASS ≡ INS
AND ISCORES ⊗ INS ≡ ISC DO
BEGIN "DO_INSTR"
HEADING1(PARMS, NINS, INS); α Print heading;
FOR Q←1 TIL !NINS_Q DO α print scores for each instr question;
BEGIN "DO_INSTR_Q"
IF SKIPAFTER[Q] THEN α need to start new page;
HEADING2(PARMS, NINS, INS);
OUT(OUTCHAN, "~F3" & QUESTION[Q]); α New font & print q;
α Note that QUESTION elements have CRLF already attached;
OUT(OUTCHAN, "~F4"); α Change font;
α Print out answer headings;
M←"S";
FOR I←1 TIL MAXSCORES[Q] % 2 DO
BEGIN
TMPMARG(⊂M⊃, ⊂(M+3)⊃);
OUT(OUTCHAN, ANSWER[ANSTYPE[Q], I]);
M←M+2;
END;
TMPMARG(⊂"↑"⊃, ⊂"a"⊃);
OUT(OUTCHAN, "mean~.");
TMPMARG(⊂"a"⊃, ⊂"b"⊃);
OUT(OUTCHAN, "overall mean" & CRLF & LF);
α Print out scores;
M←"S"; SUM←RESPS←0;
FOR R←1 TIL MAXSCORES[Q] DO
BEGIN
TMPMARG(⊂M⊃, ⊂(M←M+1)⊃); α Set margins and center;
IF I←DATUM(ISC)[Q,R] THEN
BEGIN
OUT(OUTCHAN, CVS(I));
SUM←SUM+R*I; α weighted sum of scores being formed;
RESPS←RESPS+I; α # answers to question q;
END
ELSE OUT(OUTCHAN, "--");
OUT(OUTCHAN, "~.");
END;
α If any responses, print instructor mean for question Q;
IF RESPS THEN
BEGIN
TMPMARG(⊂"↑"⊃, ⊂"a"⊃);
OUT(OUTCHAN, CVF(SUM/(RESPS*2)));
OUT(OUTCHAN, "~.");
END;
α Print overall mean;
TMPMARG(⊂"a"⊃, ⊂"b"⊃);
OUT(OUTCHAN, CVF(OVMEANS[Q]) & CRLF);
α Print percentages;
M←"S";
FOR R←1 TIL MAXSCORES[Q] DO
BEGIN
TMPMARG(⊂M⊃, ⊂(M←M+1)⊃);
OUT(OUTCHAN, IF I←DATUM(ISC)[Q,R] THEN
CVF((100*I)/RESPS) & "%"
ELSE "--");
OUT(OUTCHAN, "~.");
END;
OUT(OUTCHAN, CRLF & LF & LF);
END "DO_INSTR_Q";
END "DO_INSTR";
α Print data for t.a.s;
FOREACH X | NUMBER_OF_TAS ⊗ CLASS ≡ X DO NTAS←DATUM(X);
J←FALSE;
FOREACH TA, TSC | TEACHASST ⊗ CLASS ≡ TA
AND TSCORES ⊗ TA ≡ TSC DO
BEGIN "DO_TA"
HEADING3(PARMS, NTAS, TA, J←NOT J); α Print heading (2 t.a.s per page);
FOR Q←1 TIL !NTA_Q DO α print scores for each t.a. question;
BEGIN "DO_TA_Q"
Q1←Q+!NINS_Q; α Q1 is the actual question index;
IF SKIPAFTER[Q1] THEN α need to start new page;
HEADING2(PARMS, NTAS, TA);
OUT(OUTCHAN, "~F3" & QUESTION[Q1]); α New font & print q;
α Note that QUESTION elements have CRLF already attached;
OUT(OUTCHAN, "~F4"); α Change font;
α Print out answer headings;
M←"S";
FOR I←1 TIL MAXSCORES[Q1] % 2 DO
BEGIN
TMPMARG(⊂M⊃, ⊂(M+3)⊃);
OUT(OUTCHAN, ANSWER[ANSTYPE[Q1], I]);
M←M+2;
END;
TMPMARG(⊂"↑"⊃, ⊂"a"⊃);
OUT(OUTCHAN, "mean~.");
TMPMARG(⊂"a"⊃, ⊂"b"⊃);
OUT(OUTCHAN, "overall mean" & CRLF & LF);
α Print out scores;
M←"S"; SUM←RESPS←0;
FOR R←1 TIL MAXSCORES[Q1] DO
BEGIN
TMPMARG(⊂M⊃, ⊂(M←M+1)⊃); α Set margins and center;
IF I←DATUM(TSC)[Q,R] THEN
BEGIN
OUT(OUTCHAN, CVS(I));
SUM←SUM+R*I; α weighted sum of scores being formed;
RESPS←RESPS+I; α # answers to question q;
END
ELSE OUT(OUTCHAN, "--");
OUT(OUTCHAN, "~.");
END;
α If any responses, print t.a. mean for question Q;
IF RESPS THEN
BEGIN
TMPMARG(⊂"↑"⊃, ⊂"a"⊃);
OUT(OUTCHAN, CVF(SUM/(RESPS*2)));
OUT(OUTCHAN, "~.");
END;
α Print overall mean;
TMPMARG(⊂"a"⊃, ⊂"b"⊃);
OUT(OUTCHAN, CVF(OVMEANS[Q1]) & CRLF);
α Print percentages;
M←"S";
FOR R←1 TIL MAXSCORES[Q1] DO
BEGIN
TMPMARG(⊂M⊃, ⊂(M←M+1)⊃);
OUT(OUTCHAN, IF I←DATUM(TSC)[Q,R] THEN
CVF((100*I)/RESPS) & "%"
ELSE "--");
OUT(OUTCHAN, "~.");
END;
OUT(OUTCHAN, CRLF & LF & LF);
END "DO_TA_Q";
END "DO_TA";
END "DO_EACH_CLASS";
CLOSO(OUTCHAN);
END "DO_OUTPUT";
α The main part of the main program;
α Get input and output file names;
OUTSTR(CRLF & "SOURCE FILES? ");
SOURCEFILES←INCHWL;
OUTSTR("FILE FOR RESULTS? ");
RESULTFILE←INCHWL;
α Start processing;
DO_INPUT(SOURCEFILES, CLASSLIST, MAXSCORES, TOTALANS, TOTALSCORES);
OUTSTR(CRLF & "INPUT PROCESSING COMPLETED." & CRLF);
LBL: FOR Q←1 TIL !N_Q DO OVMEANS[Q]←TOTALSCORES[Q]/(TOTALANS[Q]*2);
DO_OUTPUT(RESULTFILE, CLASSLIST, MAXSCORES, OVMEANS);
OUTSTR(CRLF & "OUTPUT PROCESSING COMPLETED." & CRLF);
END "QPROC";